﻿using System;
using System.Data;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Reflection;
using System.IO;

namespace Fugle
{
    /// <summary>
    /// 数据访问进一步封装类
    /// </summary>
    public partial class FgSQL
    {
      public EnumDBType DBType { get; set; } = EnumDBType.SQLDb;
        private void ConnIsCheck()
        {
            var cns = System.Configuration.ConfigurationManager.ConnectionStrings[DBname];
            if (cns == null || string.IsNullOrEmpty(cns.ConnectionString))
            {
                // FgConnExt.LoadConn();
                //return;
                throw new Exception("未找到名称为[" + DBname + "]的数据库配置节点");
            }
            switch (cns.ProviderName)
            {
                default:
                    DBType = EnumDBType.SQLDb;
                    break;
                case "System.Data.SqlClient":
                    DBType = EnumDBType.SQLDb;
                    break;
                case "System.Data.OracleClient":
                    DBType = EnumDBType.OraDb;
                    break;
            }
        }
        private string AnalyzeConnectionString(string connStr)
        {
            try
            {
                if (string.IsNullOrEmpty(connStr)) return connStr;
                var items = connStr.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                var dicItems = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                foreach (var item in items)
                {
                    var val = item.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    if (val.Length > 1)
                    {
                        dicItems[val[0].Trim()] = val[1].Trim();
                    }
                }
                if (dicItems.ContainsKey("Direct")) dicItems.Remove("Direct");
                if (dicItems.ContainsKey("Unicode")) dicItems.Remove("Unicode");
                if (dicItems.ContainsKey("Server"))
                {
                    var server = dicItems["Server"];
                    dicItems["Data Source"] = server
                                        + (dicItems.ContainsKey("Port") && !server.Contains(":") && !server.Contains("/") ? ":" + dicItems["Port"] : "")
                                        + (dicItems.ContainsKey("Service Name") && !server.Contains("/") ? "/" + dicItems["Service Name"] : "");
                    dicItems.Remove("Server");
                    if (dicItems.ContainsKey("Port")) dicItems.Remove("Port");
                    if (dicItems.ContainsKey("Service Name")) dicItems.Remove("Service Name");
                }
                if (dicItems.ContainsKey("uid"))
                {
                    dicItems["User ID"] = dicItems["uid"];
                    dicItems.Remove("uid");
                }
                var _connStr = "";
                foreach (var item in dicItems)
                {
                    _connStr += item.Key + "=" + item.Value + ";";
                }
                return _connStr;
            }
            catch
            {
                return connStr;
            }
        }

        /// <summary>
        /// 获取数据库类型并返回连接字符串
        /// </summary>
        /// <param name="DBname">连接字符串唯一值</param>
        /// <param name="ConnStr">连接字符串</param>
        /// <returns>数据库类型</returns>
        private EnumDBType GetDBTypeAndConnStr(string DBname, ref string ConnStr)
        {
            ConnIsCheck();
            var c = System.Configuration.ConfigurationManager.ConnectionStrings[DBname];
            if (c != null)
            {
                switch (c.ProviderName)
                {
                    default:
                        DBType = EnumDBType.SQLDb;
                        break;
                    case "System.Data.SqlClient":
                        DBType = EnumDBType.SQLDb;
                        break;
                    case "System.Data.OracleClient":
                        DBType = EnumDBType.OraDb;
                        break;
                }
                ConnStr = AnalyzeConnectionString(c.ConnectionString);
            }
            if (c == null)
            {
                throw new Exception("未找到名称为[" + DBname + "]的数据库配置节点");
            }
            return DBType;
        }

        /// <summary>
        /// 批量插入数据(OracleBulkCopy,SqlBulkCopy方式)
        /// oracle要与当前客户端的Oracle.DataAccess.dll匹配,分32位与64位
        /// </summary>
        /// <param name="table">数据表</param>
        /// <param name="targetTableName">数据库目标表名</param>
        /// <returns></returns>
        public bool ExcuteBulkData(DataTable table, string targetTableName)
        {
            return ExcuteBulkData(table, targetTableName, 30);
        }

        /// <summary>
        /// 批量插入数据(OracleBulkCopy,SqlBulkCopy方式)
        /// oracle要与当前客户端的Oracle.DataAccess.dll匹配,分32位与64位
        /// </summary>
        /// <param name="table">数据表</param>
        /// <param name="targetTableName">数据库目标表名</param>
        /// <returns></returns>
        public bool ExcuteBulkData(DataTable table, string targetTableName, int outTime = 30)
        {
            bool result = false;
            var err = string.Empty;
            try
            {
                var _ConnectionString = string.Empty;
                EnumDBType _EnumDBType = GetDBTypeAndConnStr(DBname, ref _ConnectionString);
                if (_EnumDBType == EnumDBType.OraDb)
                {
                    result = FgOracleHelperM.ExcuteBulkData(_ConnectionString, table, targetTableName, ref err, outTime) > 0;
                }
                else
                {
                    using (SqlConnection conn = new SqlConnection(_ConnectionString))
                    {
                        conn.Open();
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(_ConnectionString, SqlBulkCopyOptions.Default))
                        {
                            if (table != null && table.Rows.Count > 0)
                            {
                                bulkCopy.BulkCopyTimeout = outTime;
                                bulkCopy.DestinationTableName = targetTableName;
                                foreach (DataColumn column in table.Columns)
                                    bulkCopy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
                                bulkCopy.WriteToServer(table);
                                result = true;
                            }
                        }
                        conn.Close();
                    }
                }
                if (!string.IsNullOrEmpty(err)) throw new Exception(err);
            }
            catch (Exception e)
            {
                new FgLogHelperPro(DBname + "_SQL异常信息").Write.Error("批量写入表[" + targetTableName + "]异常", e);
                FgLogHelper.Write("批量写入表[" + targetTableName + "]异常", "FgSQL异常:" + e.Message, EnumLogPoiority.High, EnumLogType.Error);
                throw;
            }
            return result;
        }
    }
}